package cn.itsource.pethome.base.service.impl;

import cn.itsource.pethome.base.domain.dto.BinderDTO;
import cn.itsource.pethome.base.domain.dto.LoginDTO;
import cn.itsource.pethome.base.domain.dto.WechatDTO;
import cn.itsource.pethome.base.service.ILoginService;
import cn.itsource.pethome.constants.BaseConstants;
import cn.itsource.pethome.user.domain.Logininfo;
import cn.itsource.pethome.user.domain.User;
import cn.itsource.pethome.user.domain.Wxuser;
import cn.itsource.pethome.user.mapper.LogininfoMapper;
import cn.itsource.pethome.user.mapper.UserMapper;
import cn.itsource.pethome.user.mapper.WxuserMapper;
import cn.itsource.pethome.user.service.IUserService;
import cn.itsource.pethome.util.AjaxResult;
import cn.itsource.pethome.util.BusinessException;
import cn.itsource.pethome.util.HttpClientUtils;
import cn.itsource.pethome.util.MD5Utils;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class LoginServiceImpl implements ILoginService {
    @Autowired
    private LogininfoMapper logininfoMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private WxuserMapper wxuserMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private IUserService iUserService;

    @Transactional
    @Override
    public Map<String, Object> LoginLeb(LoginDTO loginDTO) {
        //判断是输入账号是否为空
        if(StringUtils.isEmpty(loginDTO.getUsername())){
            throw  new BusinessException("账号不能为空");
        }
        //判断是密码是否为空
        if(StringUtils.isEmpty(loginDTO.getPassword())){
            throw  new BusinessException("密码不能为空");
        }
        //判断是type是否为空
        if(StringUtils.isEmpty(loginDTO.getType())){
            throw  new BusinessException("Type不能为空");
        }
        //根据账号获取logininfo对象
        Logininfo logininfo = logininfoMapper.loginfoByName(loginDTO);
        if(logininfo ==null){
            throw  new BusinessException("当前账户不存在，请重新输入");
        }
        String salt = logininfo.getSalt();
        String psad = MD5Utils.encrypByMd5(loginDTO.getPassword() + salt);
        if(!logininfo.getPassword().equals(psad)){
            throw  new BusinessException("当前输入的账号或者密码错误");
        }
        //设置token
        String token = UUID.randomUUID().toString();
        //存入redis中去
        redisTemplate.opsForValue().set(token,logininfo,30, TimeUnit.MINUTES);
        Map<String, Object> map = new HashMap<>();
        map.put("token",token);
        map.put("userinfo",logininfo);

        return map;
    }


    @Override
    public AjaxResult wechat(WechatDTO wechatDTO) {
        if(StringUtils.isEmpty(wechatDTO.getCode())//参数校验
                ||StringUtils.isEmpty(wechatDTO.getBinderUrl())){
            throw new BusinessException("非法登录");
        }
        //去获取 access_token 和 openId   替换里面的值
        String url = BaseConstants.WxConstants.GETACCESS_TOKEN_URL
                .replace("APPID",BaseConstants.WxConstants.APPID)
                .replace("SECRET",BaseConstants.WxConstants.SECRET)
                .replace("CODE",wechatDTO.getCode());
        String result = HttpClientUtils.httpGet(url);
        JSONObject jsonObject = JSONObject.parseObject(result);//将json字符串转为json对象
        //得到access_token 和 openid
        String access_token = jsonObject.getString("access_token");
        String openid = jsonObject.getString("openid");
        //根据openid去查询数据 看有没有绑定的
        Wxuser wxuser = wxuserMapper.queryByOpenId(openid);
        if(wxuser==null){
            //拼接 绑定页面的链接
            String data =wechatDTO.getBinderUrl()+"?"+"access_token="+access_token+"&openid="+openid;
            return AjaxResult.me().setSuccess(false).setMsg("NoBinder").setData(data);
        }
        //完成微信登录
        Long userId = wxuser.getUserId();
        User user = userMapper.queryOne(userId);
        Long logininfoId = user.getLogininfoId();
        Logininfo logininfo = logininfoMapper.queryOne(logininfoId);
        Map<String, Object> stringObjectMap = resultToken(logininfo);
        return AjaxResult.me().setData(stringObjectMap);
    }

    @Override
    public AjaxResult binder(BinderDTO binderDTO) {
        //验证
        if(StringUtils.isEmpty(binderDTO.getPhone())
                ||StringUtils.isEmpty(binderDTO.getAccess_token())
                ||StringUtils.isEmpty(binderDTO.getVerifyCode())
                ||StringUtils.isEmpty(binderDTO.getOpenid())
        ){
            throw new BusinessException("非法请求");
        }
        //校验验证码
        String key = BaseConstants.register.BINDER+binderDTO.getPhone();
        Object code = redisTemplate.opsForValue().get(key);
        if(code == null){
            throw new BusinessException("验证码已失效");
        }
        if(!code.toString().split(":")[0].equalsIgnoreCase(binderDTO.getVerifyCode())){
            throw new BusinessException("验证码输入错误");
        }

        //通过 access_token 和  openid 去获取用户信息
        String url = BaseConstants.WxConstants.GETWXUSER_URL
                .replace("ACCESS_TOKEN",binderDTO.getAccess_token())
                .replace("OPENID",binderDTO.getOpenid());
        //获取微信的用户信息
        String result = HttpClientUtils.httpGet(url);
        Wxuser wxuser = JSONObject.parseObject(result, Wxuser.class);
        //根据手机号去查询用户  之前注册了用户 但是没有绑定微信
        User user = userMapper.queryByPhone(binderDTO.getPhone());
        if(user == null){
            user = new User();
            user.setPassword("111111");//后台自动生成
            user.setPhone(binderDTO.getPhone());
            user.setUsername(binderDTO.getPhone());
            iUserService.insert(user);
            //发送短信
        }
        wxuser.setUserId(user.getId());
        wxuserMapper.insert(wxuser);
        //获取登录信息
        Logininfo logininfo = logininfoMapper.queryOne(user.getLogininfoId());
        //生成token
        Map<String, Object> stringObjectMap = resultToken(logininfo);
        return AjaxResult.me().setData(stringObjectMap);
    }

    private Map<String, Object> resultToken(Logininfo logininfo) {
        //生成token   每一个人生成的token必须唯一
        String token = UUID.randomUUID().toString();//请注意
        //key 是token  value 是账号数据 过期时间30分钟
        redisTemplate.opsForValue().set(token,logininfo,30, TimeUnit.MINUTES);
        Map<String,Object> map = new HashMap();
        map.put("token",token);
        //很严重的问题 不能将盐值和密码暴露出去
        logininfo.setSalt("");
        logininfo.setPassword("");
        map.put("userinfo",logininfo);
        return map;
    }

}
